<!DOCTYPE html>
<html>

<head>
  <title>Quarkus - Using OAuth2 RBAC</title>
  <script id="adobe_dtm" src="https://www.redhat.com/dtm.js" type="text/javascript"></script>
  <script src="/assets/javascript/highlight.pack.js" type="text/javascript"></script>
  <META HTTP-EQUIV='Content-Security-Policy' CONTENT="default-src 'none'; script-src 'self' 'unsafe-eval' 'sha256-ANpuoVzuSex6VhqpYgsG25OHWVA1I+F6aGU04LoI+5s=' 'sha256-ipy9P/3rZZW06mTLAR0EnXvxSNcnfSDPLDuh3kzbB1w=' js.bizographics.com https://www.redhat.com assets.adobedtm.com jsonip.com https://ajax.googleapis.com https://www.googletagmanager.com https://www.google-analytics.com https://use.fontawesome.com; style-src 'self' https://fonts.googleapis.com https://use.fontawesome.com; img-src 'self' *; media-src 'self' ; frame-src https://www.googletagmanager.com https://www.youtube.com; frame-ancestors 'none'; base-uri 'none'; object-src 'none'; form-action 'none'; font-src 'self' https://use.fontawesome.com https://fonts.gstatic.com;">
  <META HTTP-EQUIV='X-Frame-Options' CONTENT="DENY">
  <META HTTP-EQUIV='X-XSS-Protection' CONTENT="1; mode=block">
  <META HTTP-EQUIV='X-Content-Type-Options' CONTENT="nosniff">
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="description" content="Quarkus: Supersonic Subatomic Java">
  <meta name="twitter:card" content="summary_large_image">
  <meta name="twitter:site" content="@QuarkusIO"> 
  <meta name="twitter:creator" content="@QuarkusIO">
  <meta property="og:url" content="https://quarkus.io/guides/security-oauth2" />
  <meta property="og:title" content="Quarkus - Using OAuth2 RBAC" />
  <meta property="og:description" content="Quarkus: Supersonic Subatomic Java" />
  <meta property="og:image" content="/assets/images/quarkus_card.png" />
  <link rel="canonical" href="https://quarkus.io/guides/security-oauth2">
  <link rel="shortcut icon" type="image/png" href="/favicon.ico" >
  <link rel="stylesheet" href="https://quarkus.io/guides/stylesheet/config.css" />
  <link rel="stylesheet" href="/assets/css/main.css" />
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous">
  <link rel="alternate" type="application/rss+xml"  href="https://quarkus.io/feed.xml" title="Quarkus">
  <script src="https://quarkus.io/assets/javascript/goan.js" type="text/javascript"></script>
  <script src="https://quarkus.io/assets/javascript/hl.js" type="text/javascript"></script>
</head>

<body class="guides">
  <!-- Google Tag Manager (noscript) -->
  <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-NJWS5L"
  height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
  <!-- End Google Tag Manager (noscript) -->

  <div class="nav-wrapper">
  <div class="grid-wrapper">
    <div class="width-12-12">
      <input type="checkbox" id="checkbox" />
      <nav id="main-nav" class="main-nav">
  <div class="container">
    <div class="logo-wrapper">
      
        <a href="/"><img src="/assets/images/quarkus_logo_horizontal_rgb_600px_reverse.png" class="project-logo" title="Quarkus"></a>
      
    </div>
    <label class="nav-toggle" for="checkbox">
      <i class="fa fa-bars"></i>
    </label>
    <div id="menu" class="menu">
      <span>
        <a href="/get-started/" class="">Get Started</a>
      </span>
      <span>
        <a href="/guides/" class="active">Guides</a>
      </span>
      <span>
        <a href="/community/" class="">Community</a>
      </span>
      <span>
        <a href="/support/" class="">Support</a>
      </span>
      <span>
        <a href="/blog/" class="">Blog</a>
      </span>
      <span>
        <a href="https://code.quarkus.io" class="button-cta secondary white">Start Coding</a>
      </span>
    </div>
  </div>
      </nav>
    </div>
  </div>
</div>

  <div class="content">
    <div class="guide">
  <div class="width-12-12">
    <h1 class="text-caps">Quarkus - Using OAuth2 RBAC</h1>
    <div class="hide-mobile toc"><ul class="sectlevel1">
<li><a href="#solution">Solution</a></li>
<li><a href="#creating-the-maven-project">Creating the Maven project</a>
<ul class="sectlevel2">
<li><a href="#examine-the-jax-rs-resource">Examine the JAX-RS resource</a></li>
</ul>
</li>
<li><a href="#run-the-application">Run the application</a></li>
<li><a href="#configuring-the-elytron-security-oauth2-extension-security-information">Configuring the Elytron Security OAuth2 Extension Security Information</a>
<ul class="sectlevel2">
<li><a href="#setting-up-application-properties">Setting up application.properties</a></li>
<li><a href="#generating-a-token">Generating a token</a></li>
</ul>
</li>
<li><a href="#finally-secured-access-to-securedroles-allowed">Finally, Secured Access to /secured/roles-allowed</a></li>
<li><a href="#roles-mapping">Roles mapping</a></li>
<li><a href="#package-and-run-the-application">Package and run the application</a></li>
<li><a href="#integration-testing">Integration testing</a></li>
</ul></div>
    <div>
      <div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>This guide explains how your Quarkus application can utilize OAuth2 tokens to provide secured access to the JAX-RS endpoints.</p>
</div>
<div class="paragraph">
<p>OAuth2 is an authorization framework that enables applications to obtain access to an HTTP resource on behalf of a user.
It can be used to implement an application authentication mechanism based on tokens by delegating to an external server (the authentication server) the user authentication and providing a token for the authentication context.</p>
</div>
<div class="paragraph">
<p>This extension provides a light-weight support for using the opaque Bearer Tokens and validating them by calling an introspection endpoint.</p>
</div>
<div class="paragraph">
<p>If the OAuth2 Authentication server provides JWT Bearer Tokens then you should consider using either <a href="security-openid-connect">OpenId Connect</a> or <a href="security-jwt">MicroProfile JWT RBAC</a> extensions instead.
OpenId Connect extension has to be used if the Quarkus application needs to authenticate the users using OIDC Authorization Code Flow, please read <a href="security-openid-connect-web-authentication">Using OpenID Connect to Protect Web Applications</a> guide for more information.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>This technology is considered preview.</p>
</div>
<div class="paragraph">
<p>In <em>preview</em>, backward compatibility and presence in the ecosystem is not guaranteed.
Specific improvements might require to change configuration or APIs and plans to become <em>stable</em> are under way.
Feedback is welcome on our <a href="https://groups.google.com/d/forum/quarkus-dev">mailing list</a> or as issues in our <a href="https://github.com/quarkusio/quarkus/issues">GitHub issue tracker</a>.</p>
</div>
<div class="paragraph">
<p>For a full list of possible extension statuses, check our <a href="https://quarkus.io/faq/#extension-status">FAQ entry</a>.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="solution"><a class="anchor" href="#solution"></a>Solution</h2>
<div class="sectionbody">
<div class="paragraph">
<p>We recommend that you follow the instructions in the next sections and create the application step by step.
However, you can go right to the completed example.</p>
</div>
<div class="paragraph">
<p>Clone the Git repository: git clone <a href="https://github.com/quarkusio/quarkus-quickstarts.git" class="bare">https://github.com/quarkusio/quarkus-quickstarts.git</a>, or download an archive.</p>
</div>
<div class="paragraph">
<p>The solution is located in the <code>security-oauth2-quickstart</code> <a href="https://github.com/quarkusio/quarkus-quickstarts/tree/master/security-oauth2-quickstart">directory</a>.
It contains a very simple UI to use the JAX-RS resources created here, too.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="creating-the-maven-project"><a class="anchor" href="#creating-the-maven-project"></a>Creating the Maven project</h2>
<div class="sectionbody">
<div class="paragraph">
<p>First, we need a new project. Create a new project with the following command:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">mvn io.quarkus:quarkus-maven-plugin:1.7.0.Final:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=security-oauth2-quickstart \
    -DclassName="org.acme.security.oauth2.TokenSecuredResource" \
    -Dpath="/secured" \
    -Dextensions="resteasy-jsonb, security-oauth2"
cd security-oauth2-quickstart</code></pre>
</div>
</div>
<div class="paragraph">
<p>This command generates the Maven project with a REST endpoint and imports the <code>elytron-security-oauth2</code> extension, which includes the OAuth2 opaque token support.</p>
</div>
<div class="paragraph">
<p>If you don&#8217;t want to use the Maven plugin, you can just include the dependency in your pom.xml:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="xml" class="language-xml hljs">&lt;dependency&gt;
    &lt;groupId&gt;io.quarkus&lt;/groupId&gt;
    &lt;artifactId&gt;quarkus-elytron-security-oauth2&lt;/artifactId&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="sect2">
<h3 id="examine-the-jax-rs-resource"><a class="anchor" href="#examine-the-jax-rs-resource"></a>Examine the JAX-RS resource</h3>
<div class="paragraph">
<p>Open the <code>src/main/java/org/acme/security/oauth2/TokenSecuredResource.java</code> file and see the following content:</p>
</div>
<div class="listingblock">
<div class="title">Basic REST Endpoint</div>
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">package org.acme.security.oauth2;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/secured")
public class TokenSecuredResource {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "hello";
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>This is a basic REST endpoint that does not have any of the Elytron Security OAuth2 specific features, so let&#8217;s add some.</p>
</div>
<div class="paragraph">
<p>We will use the JSR 250 common security annotations, they are described in the <a href="security">Using Security</a> guide.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">package org.acme.security.oauth2;

import java.security.Principal;

import javax.annotation.security.PermitAll;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.SecurityContext;

@Path("/secured")
@ApplicationScoped
public class TokenSecuredResource {


    @GET()
    @Path("permit-all")
    @PermitAll <i class="conum" data-value="1"></i><b>(1)</b>
    @Produces(MediaType.TEXT_PLAIN)
    public String hello(@Context SecurityContext ctx) { <i class="conum" data-value="2"></i><b>(2)</b>
        Principal caller =  ctx.getUserPrincipal(); <i class="conum" data-value="3"></i><b>(3)</b>
        String name = caller == null ? "anonymous" : caller.getName();
        String helloReply = String.format("hello + %s, isSecure: %s, authScheme: %s", name, ctx.isSecure(), ctx.getAuthenticationScheme());
        return helloReply; <i class="conum" data-value="4"></i><b>(4)</b>
    }
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td><code>@PermitAll</code> indicates that the given endpoint is accessible by any caller, authenticated or not.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>Here we inject the JAX-RS <code>SecurityContext</code> to inspect the security state of the call.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>Here we obtain the current request user/caller <code>Principal</code>. For an unsecured call this will be null, so we build the user name by checking <code>caller</code> against null.</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>The reply we build up makes use of the caller name, the <code>isSecure()</code> and <code>getAuthenticationScheme()</code> states of the request <code>SecurityContext</code>.</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="run-the-application"><a class="anchor" href="#run-the-application"></a>Run the application</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Now we are ready to run our application. Use:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">./mvnw compile quarkus:dev</code></pre>
</div>
</div>
<div class="paragraph">
<p>and you should see output similar to:</p>
</div>
<div class="listingblock">
<div class="title">quarkus:dev Output</div>
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">$ ./mvnw clean compile quarkus:dev
[INFO] Scanning for projects...
[INFO]
[INFO] ---------------------&lt; org.acme:security-oauth2-quickstart &gt;---------------------
[INFO] Building security-oauth2-quickstart 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
...
[INFO] --- quarkus-maven-plugin:999-SNAPSHOT:dev (default-cli) @ security-oauth2-quickstart ---
Listening for transport dt_socket at address: 5005
2019-07-16 09:58:09,753 INFO  [io.qua.dep.QuarkusAugmentor] (main) Beginning quarkus augmentation
2019-07-16 09:58:10,884 INFO  [io.qua.dep.QuarkusAugmentor] (main) Quarkus augmentation completed in 1131ms
2019-07-16 09:58:11,385 INFO  [io.quarkus] (main) Quarkus 0.20.0 started in 1.813s. Listening on: http://[::]:8080
2019-07-16 09:58:11,391 INFO  [io.quarkus] (main) Installed features: [cdi, resteasy, resteasy-jsonb, security, security-oauth2]</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now that the REST endpoint is running, we can access it using a command line tool like curl:</p>
</div>
<div class="listingblock">
<div class="title">curl command for /secured/permit-all</div>
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">$ curl http://127.0.0.1:8080/secured/permit-all; echo
hello + anonymous, isSecure: false, authScheme: null</code></pre>
</div>
</div>
<div class="paragraph">
<p>We have not provided any token in our request, so we would not expect that there is any security state seen by the endpoint, and the response is consistent with that:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>user name is anonymous</p>
</li>
<li>
<p><code>isSecure</code> is false as https is not used</p>
</li>
<li>
<p><code>authScheme</code> is null</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>So now let&#8217;s actually secure something. Take a look at the new endpoint method <code>helloRolesAllowed</code> in the following:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">package org.acme.security.oauth2;

import java.security.Principal;

import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.SecurityContext;

@Path("/secured")
@ApplicationScoped
public class TokenSecuredResource {

    @GET()
    @Path("permit-all")
    @PermitAll
    @Produces(MediaType.TEXT_PLAIN)
    public String hello(@Context SecurityContext ctx) {
        Principal caller =  ctx.getUserPrincipal();
        String name = caller == null ? "anonymous" : caller.getName();
        String helloReply = String.format("hello + %s, isSecure: %s, authScheme: %s", name, ctx.isSecure(), ctx.getAuthenticationScheme());
        return helloReply;
    }

    @GET()
    @Path("roles-allowed") <i class="conum" data-value="1"></i><b>(1)</b>
    @RolesAllowed({"Echoer", "Subscriber"}) <i class="conum" data-value="2"></i><b>(2)</b>
    @Produces(MediaType.TEXT_PLAIN)
    public String helloRolesAllowed(@Context SecurityContext ctx) {
        Principal caller =  ctx.getUserPrincipal();
        String name = caller == null ? "anonymous" : caller.getName();
        String helloReply = String.format("hello + %s, isSecure: %s, authScheme: %s", name, ctx.isSecure(), ctx.getAuthenticationScheme());
        return helloReply;
    }
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>This new endpoint will be located at <code>/secured/roles-allowed</code></td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td><code>@RolesAllowed</code> indicates that the given endpoint is accessible by a caller if they have either a "Echoer" or "Subscriber" role assigned.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>After you make this addition to your <code>TokenSecuredResource</code>, try <code>curl -v <a href="http://127.0.0.1:8080/secured/roles-allowed" class="bare">http://127.0.0.1:8080/secured/roles-allowed</a>; echo</code> to attempt to access the new endpoint. Your output should be:</p>
</div>
<div class="listingblock">
<div class="title">curl command for /secured/roles-allowed</div>
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">$ curl -v http://127.0.0.1:8080/secured/roles-allowed; echo
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
&gt; GET /secured/roles-allowed HTTP/1.1
&gt; Host: 127.0.0.1:8080
&gt; User-Agent: curl/7.54.0
&gt; Accept: */*
&gt;
&lt; HTTP/1.1 401 Unauthorized
&lt; Connection: keep-alive
&lt; Content-Type: text/html;charset=UTF-8
&lt; Content-Length: 14
&lt; Date: Sun, 03 Mar 2019 16:32:34 GMT
&lt;
* Connection #0 to host 127.0.0.1 left intact
Not authorized</code></pre>
</div>
</div>
<div class="paragraph">
<p>Excellent, we have not provided any OAuth2 token in the request, so we should not be able to access the endpoint, and we were not. Instead we received an HTTP 401 Unauthorized error. We need to obtain and pass in a valid OAuth2 token to access that endpoint. There are two steps to this, 1) configuring our Elytron Security OAuth2 extension with information on how to validate the token, and 2) generating a matching token with the appropriate claims.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="configuring-the-elytron-security-oauth2-extension-security-information"><a class="anchor" href="#configuring-the-elytron-security-oauth2-extension-security-information"></a>Configuring the Elytron Security OAuth2 Extension Security Information</h2>
<div class="sectionbody">
<div class="paragraph configuration-legend">
<p><span class="icon"><i class="fa fa-lock" title="Fixed at build time"></i></span> Configuration property fixed at build time - All other configuration properties are overridable at runtime</p>
</div>
<table class="tableblock frame-all grid-all stretch configuration-reference searchable">
<colgroup>
<col style="width: 80%;">
<col style="width: 10%;">
<col style="width: 10%;">
</colgroup>
<tbody>
<tr>
<th class="tableblock halign-left valign-top"><p class="tableblock"><a id="quarkus-elytron-security-oauth2_configuration"></a><a href="#quarkus-elytron-security-oauth2_configuration">Configuration property</a></p></th>
<th class="tableblock halign-left valign-middle"><p class="tableblock">Type</p></th>
<th class="tableblock halign-left valign-middle"><p class="tableblock">Default</p></th>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><span class="icon"><i class="fa fa-lock" title="Fixed at build time"></i></span> <a id="quarkus-elytron-security-oauth2_quarkus.oauth2.enabled"></a><code><a href="#quarkus-elytron-security-oauth2_quarkus.oauth2.enabled">quarkus.oauth2.enabled</a></code></p>
</div>
<div class="openblock description">
<div class="content">
<div class="paragraph">
<p>Determine if the OAuth2 extension is enabled. Enabled by default if you include the <code>elytron-security-oauth2</code> dependency, so this would be used to disable it.</p>
</div>
</div>
</div></div></td>
<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><code>true</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><span class="icon"><i class="fa fa-lock" title="Fixed at build time"></i></span> <a id="quarkus-elytron-security-oauth2_quarkus.oauth2.role-claim"></a><code><a href="#quarkus-elytron-security-oauth2_quarkus.oauth2.role-claim">quarkus.oauth2.role-claim</a></code></p>
</div>
<div class="openblock description">
<div class="content">
<div class="paragraph">
<p>The claim that is used in the introspection endpoint response to load the roles.</p>
</div>
</div>
</div></div></td>
<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><code>scope</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><a id="quarkus-elytron-security-oauth2_quarkus.oauth2.client-id"></a><code><a href="#quarkus-elytron-security-oauth2_quarkus.oauth2.client-id">quarkus.oauth2.client-id</a></code></p>
</div>
<div class="openblock description">
<div class="content">
<div class="paragraph">
<p>The OAuth2 client id used to validate the token. Mandatory if the extension is enabled.</p>
</div>
</div>
</div></div></td>
<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-middle"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><a id="quarkus-elytron-security-oauth2_quarkus.oauth2.client-secret"></a><code><a href="#quarkus-elytron-security-oauth2_quarkus.oauth2.client-secret">quarkus.oauth2.client-secret</a></code></p>
</div>
<div class="openblock description">
<div class="content">
<div class="paragraph">
<p>The OAuth2 client secret used to validate the token. Mandatory if the extension is enabled.</p>
</div>
</div>
</div></div></td>
<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-middle"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><a id="quarkus-elytron-security-oauth2_quarkus.oauth2.introspection-url"></a><code><a href="#quarkus-elytron-security-oauth2_quarkus.oauth2.introspection-url">quarkus.oauth2.introspection-url</a></code></p>
</div>
<div class="openblock description">
<div class="content">
<div class="paragraph">
<p>The OAuth2 introspection endpoint URL used to validate the token and gather the authentication claims. Mandatory if the extension is enabled.</p>
</div>
</div>
</div></div></td>
<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-middle"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><a id="quarkus-elytron-security-oauth2_quarkus.oauth2.ca-cert-file"></a><code><a href="#quarkus-elytron-security-oauth2_quarkus.oauth2.ca-cert-file">quarkus.oauth2.ca-cert-file</a></code></p>
</div>
<div class="openblock description">
<div class="content">
<div class="paragraph">
<p>The OAuth2 server certificate file. <strong>Warning</strong>: this is not supported in native mode where the certificate must be included in the truststore used during the native image generation, see <a href="native-and-ssl.html">Using SSL With Native Executables</a>.</p>
</div>
</div>
</div></div></td>
<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-middle"></td>
</tr>
</tbody>
</table>
<div class="sect2">
<h3 id="setting-up-application-properties"><a class="anchor" href="#setting-up-application-properties"></a>Setting up application.properties</h3>
<div class="paragraph">
<p>For part A of step 1, create a <code>security-oauth2-quickstart/src/main/resources/application.properties</code> with the following content:</p>
</div>
<div class="listingblock">
<div class="title">application.properties for TokenSecuredResource</div>
<div class="content">
<pre class="highlightjs highlight"><code data-lang="properties" class="language-properties hljs">quarkus.oauth2.client-id=client_id
quarkus.oauth2.client-secret=secret
quarkus.oauth2.introspection-url=http://oauth-server/introspect</code></pre>
</div>
</div>
<div class="paragraph">
<p>You need to specify the introspection URL of your authentication server and the <code>client-id</code> / <code>client-secret</code> that your application will use to authenticate itself to the authentication server.</p>
</div>
<div class="paragraph">
<p>The extension will then use this information to validate the token and recover the information associate with it.</p>
</div>
</div>
<div class="sect2">
<h3 id="generating-a-token"><a class="anchor" href="#generating-a-token"></a>Generating a token</h3>
<div class="paragraph">
<p>You need to obtain the token from a standard OAuth2 authentication server (<a href="https://www.keycloak.org/">Keycloak</a> for example) using the token endpoint.</p>
</div>
<div class="paragraph">
<p>You can find below a curl example of such call for a <code>client_credential</code> flow:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">curl -X POST "http://oauth-server/token?grant_type=client_credentials" \
-H  "Accept: application/json" -H  "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ="</code></pre>
</div>
</div>
<div class="paragraph">
<p>It should respond something like that&#8230;&#8203;</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="json" class="language-json hljs">{"access_token":"60acf56d-9daf-49ba-b3be-7a423d9c7288","token_type":"bearer","expires_in":1799,"scope":"READER"}</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="finally-secured-access-to-securedroles-allowed"><a class="anchor" href="#finally-secured-access-to-securedroles-allowed"></a>Finally, Secured Access to /secured/roles-allowed</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Now let&#8217;s use this to make a secured request to the <code>/secured/roles-allowed</code> endpoint</p>
</div>
<div class="listingblock">
<div class="title">curl Command for /secured/roles-allowed With a token</div>
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">$ curl -H "Authorization: Bearer 60acf56d-9daf-49ba-b3be-7a423d9c7288" http://127.0.0.1:8080/secured/roles-allowed; echo
hello + client_id isSecure: false, authScheme: OAuth2</code></pre>
</div>
</div>
<div class="paragraph">
<p>Success! We now have:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>a non-anonymous caller name of client_id</p>
</li>
<li>
<p>an authentication scheme of OAuth2</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="roles-mapping"><a class="anchor" href="#roles-mapping"></a>Roles mapping</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Roles are mapped from one of the claims of the introspection endpoint response. By default, it&#8217;s the <code>scope</code> claim. Roles are obtained by splitting the claim with a space separator. If the claim is an array, no splitting is done, the roles are obtained from the array.</p>
</div>
<div class="paragraph">
<p>You can customize the name of the claim to use for the roles with the <code>quarkus.oauth2.role-claim</code> property.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="package-and-run-the-application"><a class="anchor" href="#package-and-run-the-application"></a>Package and run the application</h2>
<div class="sectionbody">
<div class="paragraph">
<p>As usual, the application can be packaged using <code>./mvnw clean package</code> and executed using the <code>-runner.jar</code> file:
.Runner jar Example</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">$ ./mvnw clean package
[INFO] Scanning for projects...
...
$ java -jar target/security-oauth2-quickstart-runner.jar
2019-03-28 14:27:48,839 INFO  [io.quarkus] (main) Quarkus 0.20.0 started in 0.796s. Listening on: http://[::]:8080
2019-03-28 14:27:48,841 INFO  [io.quarkus] (main) Installed features: [cdi, resteasy, resteasy-jsonb, security, security-oauth2]</code></pre>
</div>
</div>
<div class="paragraph">
<p>You can also generate the native executable with <code>./mvnw clean package -Pnative</code>.
.Native Executable Example</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">$ ./mvnw clean package -Pnative
[INFO] Scanning for projects...
...
[security-oauth2-quickstart-runner:25602]     universe:     493.17 ms
[security-oauth2-quickstart-runner:25602]      (parse):     660.41 ms
[security-oauth2-quickstart-runner:25602]     (inline):   1,431.10 ms
[security-oauth2-quickstart-runner:25602]    (compile):   7,301.78 ms
[security-oauth2-quickstart-runner:25602]      compile:  10,542.16 ms
[security-oauth2-quickstart-runner:25602]        image:   2,797.62 ms
[security-oauth2-quickstart-runner:25602]        write:     988.24 ms
[security-oauth2-quickstart-runner:25602]      [total]:  43,778.16 ms
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  51.500 s
[INFO] Finished at: 2019-06-28T14:30:56-07:00
[INFO] ------------------------------------------------------------------------

$ ./target/security-oauth2-quickstart-runner
2019-03-28 14:31:37,315 INFO  [io.quarkus] (main) Quarkus 0.20.0 started in 0.006s. Listening on: http://[::]:8080
2019-03-28 14:31:37,316 INFO  [io.quarkus] (main) Installed features: [cdi, resteasy, resteasy-jsonb, security, security-oauth2]</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="integration-testing"><a class="anchor" href="#integration-testing"></a>Integration testing</h2>
<div class="sectionbody">
<div class="paragraph">
<p>If you don&#8217;t want to use a real OAuth2 authorization server for your integration tests, you can use the
<a href="security-properties">Properties based security</a> extension for your test, or mock an authorization server using Wiremock.</p>
</div>
<div class="paragraph">
<p>First of all, Wiremock needs to be added as a test dependency. For a Maven project that would happen like so:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="xml" class="language-xml hljs">&lt;dependency&gt;
    &lt;groupId&gt;com.github.tomakehurst&lt;/groupId&gt;
    &lt;artifactId&gt;wiremock-jre8&lt;/artifactId&gt;
    &lt;scope&gt;test&lt;/scope&gt;
    &lt;version&gt;${wiremock.version}&lt;/version&gt; <i class="conum" data-value="1"></i><b>(1)</b>
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>Use a proper Wiremock version. All available versions can be found <a href="https://search.maven.org/artifact/com.github.tomakehurst/wiremock-jre8">here</a>.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>In Quarkus tests when some service needs to be started before the Quarkus tests are ran, we utilize the <code>@io.quarkus.test.common.QuarkusTestResource</code>
annotation to specify a <code>io.quarkus.test.common.QuarkusTestResourceLifecycleManager</code> which can start the service and supply configuration
values that Quarkus will use.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>For more details about <code>@QuarkusTestResource</code> refer to  <a href="getting-started-testing#quarkus-test-resource">this part of the documentation</a>.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Let&#8217;s create an implementation of <code>QuarkusTestResourceLifecycleManager</code> called <code>MockAuthorizationServerTestResource</code> like so:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.WireMock;
import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;

import java.util.Collections;
import java.util.Map;

public class MockAuthorizationServerTestResource implements QuarkusTestResourceLifecycleManager {  <i class="conum" data-value="1"></i><b>(1)</b>

    private WireMockServer wireMockServer;

    @Override
    public Map&lt;String, String&gt; start() {
        wireMockServer = new WireMockServer();
        wireMockServer.start(); <i class="conum" data-value="2"></i><b>(2)</b>

        // define the mock for the introspect endpoint
        WireMock.stubFor(WireMock.post("/introspect").willReturn(WireMock.aResponse() <i class="conum" data-value="3"></i><b>(3)</b>
                .withBody(
                        "{\"active\":true,\"scope\":\"Echoer\",\"username\":null,\"iat\":1562315654,\"exp\":1562317454,\"expires_in\":1458,\"client_id\":\"my_client_id\"}")));


        return Collections.singletonMap("quarkus.oauth2.introspection-url", wireMockServer.baseUrl() + "/introspect"); <i class="conum" data-value="4"></i><b>(4)</b>
    }

    @Override
    public void stop() {
        if (null != wireMockServer) {
            wireMockServer.stop();  <i class="conum" data-value="5"></i><b>(5)</b>
        }
    }
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>The <code>start</code> method is invoked by Quarkus before any test is run and returns a <code>Map</code> of configuration properties that apply during the test execution.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>Launch Wiremock.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>Configure Wiremock to stub the calls to <code>/introspect</code> by returning an OAuth2 introspect response. You need to customize this line to return what&#8217;s needed for your application (at least the scope property as roles are derived from the scope).</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>As the <code>start</code> method returns configuration that applies for tests, we set the <code>quarkus.oauth2.introspection-url</code> property that controls the URL of the introspect endpoint used by the OAuth2 extension.</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td>When all tests have finished, shutdown Wiremock.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Your test class needs to be annotated like with <code>@QuarkusTestResource(MockAuthorizationServerTestResource.class)</code> to use this <code>QuarkusTestResourceLifecycleManager</code>.</p>
</div>
<div class="paragraph">
<p>Below is an example of a test that uses the <code>MockAuthorizationServerTestResource</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@QuarkusTest
@QuarkusTestResource(MockAuthorizationServerTestResource.class) <i class="conum" data-value="1"></i><b>(1)</b>
class TokenSecuredResourceTest {
    // use whatever token you want as the mock OAuth server will accept all tokens
    private static final String BEARER_TOKEN = "337aab0f-b547-489b-9dbd-a54dc7bdf20d"; <i class="conum" data-value="2"></i><b>(2)</b>

    @Test
    void testPermitAll() {
        RestAssured.given()
                .when()
                .header("Authorization", "Bearer: " + BEARER_TOKEN) <i class="conum" data-value="3"></i><b>(3)</b>
                .get("/secured/permit-all")
                .then()
                .statusCode(200)
                .body(containsString("hello"));
    }

    @Test
    void testRolesAllowed() {
        RestAssured.given()
                .when()
                .header("Authorization", "Bearer: " + BEARER_TOKEN)
                .get("/secured/roles-allowed")
                .then()
                .statusCode(200)
                .body(containsString("hello"));
    }
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>Use the previously created <code>MockAuthorizationServerTestResource</code> as a Quarkus test resource.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>Define whatever token you want, it will not be validated by the OAuth2 mock authorization server.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>Use this token inside the <code>Authorization</code> header to trigger OAuth2 authentication.</td>
</tr>
</table>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
<div class="paragraph">
<p><code>@QuarkusTestResource</code> applies to all tests, not just <code>TokenSecuredResourceTest</code>.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
    </div>
  </div>
</div>

  </div>

  <div class="content project-footer">
  <div class="footer-section">
    <div class="logo-wrapper">
      <a href="/"><img src="/assets/images/quarkus_logo_horizontal_rgb_reverse.svg" class="project-logo" title="Quarkus"></a>
    </div>
  </div>
  <div class="grid-wrapper">
    <p class="grid__item width-3-12">Quarkus is open. All dependencies of this project are available under the <a href='https://www.apache.org/licenses/LICENSE-2.0' target='_blank'>Apache Software License 2.0</a> or compatible license.<br /><br />This website was built with <a href='https://jekyllrb.com/' target='_blank'>Jekyll</a>, is hosted on <a href='https://pages.github.com/' target='_blank'>Github Pages</a> and is completely open source. If you want to make it better, <a href='https://github.com/quarkusio/quarkusio.github.io' target='_blank'>fork the website</a> and show us what you’ve got.</p>

    
      <div class="width-1-12 project-links">
        <span>Navigation</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="/">Home</a></li>
          
            <li><a href="/guides">Guides</a></li>
          
            <li><a href="/community/#contributing">Contribute</a></li>
          
            <li><a href="/faq">FAQ</a></li>
          
            <li><a href="/get-started">Get Started</a></li>
          
        </ul>
      </div>
    
      <div class="width-1-12 project-links">
        <span>Contribute</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="https://twitter.com/quarkusio">Follow us</a></li>
          
            <li><a href="https://github.com/quarkusio">GitHub</a></li>
          
            <li><a href="/security">Security&nbsp;policy</a></li>
          
        </ul>
      </div>
    
      <div class="width-1-12 project-links">
        <span>Get Help</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="https://groups.google.com/forum/#!forum/quarkus-dev">Forums</a></li>
          
            <li><a href="https://quarkusio.zulipchat.com">Chatroom</a></li>
          
        </ul>
      </div>
    

    
      <div class="width-3-12 more-links">
        <span>Quarkus is made of community projects</span>
        <ul class="footer-links">
          
            <li><a href="https://vertx.io/" target="_blank">Eclipse Vert.x</a></li>
          
            <li><a href="https://microprofile.io" target="_blank">Eclipse MicroProfile</a></li>
          
            <li><a href="https://hibernate.org" target="_blank">Hibernate</a></li>
          
            <li><a href="https://netty.io" target="_blank">Netty</a></li>
          
            <li><a href="https://resteasy.github.io" target="_blank">RESTEasy</a></li>
          
            <li><a href="https://camel.apache.org" target="_blank">Apache Camel</a></li>
          
            <li><a href="https://code.quarkus.io/" target="_blank">And many more...</a></li>
          
        </ul>
      </div>
    
  </div>
</div>
  <div class="content redhat-footer">
  <div class="grid-wrapper">
    <span class="licence">
      <i class="fab fa-creative-commons"></i><i class="fab fa-creative-commons-by"></i> <a href="https://creativecommons.org/licenses/by/3.0/" target="_blank">CC by 3.0</a> | <a href="https://www.redhat.com/en/about/privacy-policy">Privacy Policy</a>
    </span>
    <span class="redhat">
      Sponsored by
    </span>
    <span class="redhat-logo">
      <a href="https://www.redhat.com/" target="_blank"><img src="/assets/images/redhat_reversed.svg"></a>
    </span>
  </div>
</div>


  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" integrity="sha384-8gBf6Y4YYq7Jx97PIqmTwLPin4hxIzQw5aDmUg/DDhul9fFpbbLcLh3nTIIDJKhx" crossorigin="anonymous"></script>
  <script type="text/javascript" src="/assets/javascript/mobile-nav.js"></script>
  <script type="text/javascript" src="/assets/javascript/scroll-down.js"></script>
  <script src="/assets/javascript/satellite.js" type="text/javascript"></script>
  <script src="https://quarkus.io/guides/javascript/config.js" type="text/javascript"></script>
  <script src="/assets/javascript/search-filter.js" type="text/javascript"></script>
  <script src="/assets/javascript/back-to-top.js" type="text/javascript"></script>
</body>

</html>
